package com.mgy.example.dao.aop;

import com.mgy.example.annotation.HintIgnore;
import com.mgy.example.domain.TableRouter;
import com.mgy.example.utils.DbUtil;
import io.shardingsphere.api.HintManager;
import io.shardingsphere.core.hint.HintManagerHolder;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.List;

/**
 * 拦截dao层数据库操作，使用hint强制分片
 *
 * @author mgy
 */
@Aspect
@Component
public class MapperAspect {
    /**
     * 切点
     * execution(* com.mgy.example.dao.mapper..*(..))
     */
    @Pointcut("execution(public * com.mgy.example.dao.mapper..*(..))")
    public void mapperPointcut() {

    }

    @Around("mapperPointcut()")
    public Object around(ProceedingJoinPoint joinPoint) throws Throwable {
        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
        Method method = methodSignature.getMethod();
        Annotation methodHintIgnore = method.getDeclaredAnnotation(HintIgnore.class);
        Class type = method.getDeclaringClass();
        Annotation typeHintIgnore = type.getDeclaredAnnotation(HintIgnore.class);
        String[] parameterNames = methodSignature.getParameterNames();
        Class[] parameterTypes = methodSignature.getMethod().getParameterTypes();
        Object[] parameterValues = joinPoint.getArgs();
        try {
            if (methodHintIgnore == null && typeHintIgnore == null) {
                List<TableRouter> tableRouterList = DbUtil.getTableRouter(parameterNames, parameterTypes, parameterValues);
                if (!CollectionUtils.isEmpty(tableRouterList)) {
                    HintManager hintManager = HintManager.getInstance();
                    for (TableRouter router : tableRouterList) {
                        if (router.getDbNo() != null) {
                            if (router.getTableNo() != null) {
                                hintManager.addDatabaseShardingValue(router.getLogicTable(), router.getDbNo());
                                hintManager.addTableShardingValue(router.getLogicTable(), router.getTableNo());
                            } else {
                                //分库不分表
                                hintManager.setDatabaseShardingValue(router.getDbNo());
                            }
                        }
                    }
                }
            }
            //执行业务方法
            return joinPoint.proceed();
        } finally {
            HintManagerHolder.clear();
        }

    }


//    @Before("mapperPointcut()")
//    public void before(JoinPoint joinPoint) {
//        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//        System.out.println(methodSignature.getMethod().getName() + "-before");
//    }
//
//    @After("mapperPointcut()")
//    public void after(JoinPoint joinPoint) {
//        MethodSignature methodSignature = (MethodSignature) joinPoint.getSignature();
//        System.out.println(methodSignature.getMethod().getName() + "-after");
//    }

}
